package timing.ukulele.auth.security.filter;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import timing.ukulele.auth.security.model.CustomGrantedAuthority;
import timing.ukulele.auth.security.model.JwtSecurityToken;
import timing.ukulele.auth.support.RedisOperator;

import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;

import static timing.ukulele.share.Constant.*;

@Slf4j
public class JWTSecurityFilter extends OncePerRequestFilter {

    private final JwtDecoder jwtDecoder;
    private final RedisOperator<String> redisOperator;

    public JWTSecurityFilter(JwtDecoder jwtDecoder, RedisOperator<String> redisOperator) {
        this.jwtDecoder = jwtDecoder;
        this.redisOperator = redisOperator;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//        //如果是要登录，放行到登录页面
//        // 从请求头中获取认证信息
        String authHeader = request.getHeader("Authorization");
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            filterChain.doFilter(request, response);
            return;
        }
        String token = authHeader.substring(7);
        if (!StringUtils.hasLength(token)) {
            filterChain.doFilter(request, response);
            return;
        }
        try {
            Jwt decode = jwtDecoder.decode(token);
            if (decode == null || decode.getExpiresAt() == null || decode.getExpiresAt().compareTo(Instant.now()) <= 0) {
                filterChain.doFilter(request, response);
                return;
            }
            // 将UserDetails存储到SecurityContextHolder中
            List<CustomGrantedAuthority> authorityList = new ArrayList<>();
            List<String> scopeList = decode.getClaimAsStringList(SCOPES_KEY);
            for (String scope : scopeList) {
                CustomGrantedAuthority auth = new CustomGrantedAuthority(scope);
                authorityList.add(auth);
            }
            // 根据缓存取用户信息
            String cacheUser = redisOperator.get(TOKEN_CACHE_PREFIX + decode.getClaimAsString("sub"));
            if (cacheUser != null) {
                JSONObject jsonObject = JSON.parseObject(cacheUser);
                String username = jsonObject.getString(TOKEN_USER_INFO_USERNAME);
                if (username != null) {
                    User user = new User(username, "", true, true, true, true, authorityList);
                    JwtSecurityToken authenticationToken = new JwtSecurityToken(user, authorityList);
                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                }
            }
        } catch (Exception exception) {
            log.error(exception.getMessage());
        }
        filterChain.doFilter(request, response);
    }
}

